from django.db.models import F
from rest_framework.pagination import PageNumberPagination
from account.models import Classify, Tag, Collect, Fans, User
from article import serializers
from article.models import Article, Comment
from utils.base_api_view import BaseAPIView, PageNumber
from utils.exceptions import PermissionDenied
from utils.permissions import IsLogin
from utils.upload import write_file_local


# 获取单个文章内容
class GetArticle(BaseAPIView):
    serializer_classes = serializers.GetArticleSerializer

    def __init__(self):
        super().__init__()
        self.article_id = None
        self.article = None

    def add_collect_info(self):
        if self.request.user.is_anonymous:
            return False
        if self.request.user.collects.filter(article__id=self.article_id, is_delete=False).exists():
            return True
        return False

    # def add_classify_tag_name(self):
    #     classify_ids = self.article.classifies.split(',')
    #     classify_ids = classify_ids if classify_ids != [''] else []
    #     classifies = Classify.objects.filter(id__in=classify_ids) \
    #         .values_list('classify_name', flat=True)
    #     tag_ids = self.article.tags.split(',')
    #     tag_ids = tag_ids if tag_ids != [''] else []
    #     tags = Tag.objects.filter(id__in=tag_ids) \
    #         .values_list('tag_name', flat=True)
    #     return classifies, tags
    #
    # def add_classify_tag_id(self, data):
    #     classifies = data.get('classifies').split(',')
    #     if classifies != ['']:
    #         classifies = [int(i) for i in classifies]
    #     else:
    #         classifies = []
    #     data['classifies'] = classifies
    #     tags = data.get('tags').split(',')
    #     if tags != ['']:
    #         tags = [int(i) for i in tags]
    #     else:
    #         tags = []
    #     data['tags'] = tags
    #     return data

    def has_permission(self):
        if self.article.public:
            return True
        else:
            if self.request.user.username == self.article.author:
                return True
        return False

    def get(self, request, *args, **kwargs):
        self.article_id = self.get_serializer_data().get('id')
        self.article = Article.objects.filter(id=self.article_id).first()
        if self.article:
            if self.has_permission:
                data = self.serializer_out(self.article)
                data['is_collected'] = self.add_collect_info()
                return self.succeed(data=data)
            else:
                raise PermissionDenied(detail='无权查看此文章')
        else:
            self.error('找不到该文章')


class DeleteArticle(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.DeleteArticleSerializer

    def get(self, request, *args, **kwargs):
        user = request.user
        article_ids = self.get_serializer_data().get('ids')
        if user.articles.filter(id__in=article_ids).exists():
            user.articles.filter(id__in=article_ids).delete()
            return self.succeed('删除成功')
        else:
            self.error('没有查询到相关文章')


class ListArticle(BaseAPIView):
    serializer_classes = serializers.ListArticleSeralizer

    def get(self, request, *args, **kwargs):
        username = self.get_serializer_data().get('user', None)
        article_list = None
        # 有用户名信息时查询指定用户的文章列表
        if username:
            if User.objects.filter(username=username).exists():
                user = User.objects.filter(username=username).first()
                article_list = user.articles.filter(public=True).order_by('-publish_time')
            else:
                self.error('没有查到相关用户')
        else:
            # 默认返回所有文章
            article_list = Article.objects.filter(public=True).order_by('-publish_time')
        return self.pagination_with_serializer(article_list)

    def old_get(self, request, *args, **kwargs):
        username = self.get_serializer_data().get('user', None)
        article_list = Article.objects.filter(public=True).order_by('-publish_time')
        # 有用户名信息时查询指定用户的文章列表
        if username:
            article_list = article_list.filter(author=username)
        pagination_obj = PageNumber()
        pagination_result = pagination_obj.paginate_queryset(article_list, request=self.request, view=self)
        untreated_data = self.serializer_out(pagination_result, many=True)
        for data in untreated_data:
            # 处理分类及标签
            classify_ids = data['classifies'].split(',')
            classify_ids = classify_ids if classify_ids != [''] else []
            classifies = Classify.objects.filter(id__in=classify_ids) \
                .values_list('classify_name', flat=True)
            tag_ids = data['tags'].split(',')
            tag_ids = tag_ids if tag_ids != [''] else []
            tags = Tag.objects.filter(id__in=tag_ids) \
                .values_list('tag_name', flat=True)
            data['classifies'] = classifies
            data['tags'] = tags
            # 文章截取部分文字
        return pagination_obj.get_paginated_response({'data': untreated_data})


class ListSelfArticle(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.ListSelfArticleSeralizer

    def __init__(self):
        super().__init__()
        self.classifies_list = []
        self.tags_list = []

    def get_classify_tag(self, classify_list, tag_list):
        classify_filter = set(classify_list)
        for classify in classify_filter:
            self.classifies_list.append({
                'text': classify,
                'value': classify
            })
        tag_filter = set(tag_list)
        for tag in tag_filter:
            self.tags_list.append({
                'text': tag,
                'value': tag
            })

    def get(self, request, *args, **kwargs):
        title_snippet = self.get_serializer_data().get('title_snippet')
        user = request.user
        article_list = user.articles.all().order_by('-publish_time')
        if title_snippet:
            article_list = article_list.filter(title__contains=title_snippet)
        return self.pagination_with_serializer(article_list)


class ListStaredUserArticle(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.ListStaredUserArticleSeralizer

    def get(self, request, *args, **kwargs):
        user = request.user
        attention_user = user.attentions.filter(is_delete=False).values_list('attention_user', flat=True)
        articles = Article.objects.filter(author__in=attention_user, public=True).order_by('-publish_time')
        return self.pagination_with_serializer(articles)


class UploadArticle(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.UploadArticleSerializer

    def __init__(self):
        super().__init__()
        self.data = None

    def post(self, request, *args, **kwargs):
        self.data = self.post_serializer_data()
        # print(self.data)
        if self.data.get('is_modify'):
            return self.update(self.data.get('modify_id'))
        else:
            return self.save()

    def clear_data(self):
        need_clear_list = ['is_modify', 'modify_id', 'classifies', 'tags']
        for i in need_clear_list:
            try:
                self.data.pop(i)
            except KeyError:
                pass

    def get_classifies_tags(self):
        # 把 '1,2,3' 转化为 ['1', '2', '3']
        classifies_str = self.data.get('classifies')
        tags_str = self.data.get('classifies')
        classifies, tags = None, None
        if classifies_str:
            classifies = Classify.objects.filter(id__in=classifies_str.split(','))\
                .order_by('id').values_list('id', flat=True)
        if tags_str:
            tags = Tag.objects.filter(id__in=tags_str.split(',')).order_by('id')\
                .values_list('id', flat=True)
        self.clear_data()
        return classifies, tags

    def update(self, article_id):
        classifies, tags = self.get_classifies_tags()
        username = self.request.user.username
        if Article.objects.filter(id=article_id).exists():
            article = Article.objects.filter(id=article_id).first()
            if username == article.author or self.request.user.is_admin:
                Article.objects.filter(id=article_id).update(**self.data)
                if article.classifies.order_by('id').values_list('id') != classifies:
                    article.classifies.clear()
                    article.classifies.add(*classifies)
                if article.tags.order_by('id').values_list('id') != tags:
                    article.tags.clear()
                    article.tags.add(*tags)
                article.save()
                return self.succeed('修改成功')
            else:
                raise PermissionDenied()
        else:
            self.error('没有找到该文章')

    def save(self):
        classifies, tags = self.get_classifies_tags()
        article = Article.objects.create(**self.data, author=self.request.user)
        if classifies:
            article.classifies.add(*classifies)
        if tags:
            article.tags.add(*tags)
        article.save()
        if article:
            return self.succeed('保存成功')
        else:
            self.error('创建失败')


class CommentArticle(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.CommentArticleSerializer

    def post(self, request, *args, **kwargs):
        user = request.user
        data = self.post_serializer_data()
        comment = Comment.objects.create(**data)
        comment.user = user
        comment.save()
        if comment:
            return self.succeed(data=self.serializer_out(comment))
        self.error('评论失败')


class ListArticleComment(BaseAPIView):
    serializer_classes = serializers.ListArticleCommentSerializer

    class CommentPageNumber(PageNumberPagination):
        page_size = 3  # 每页显示多少条
        page_size_query_param = 'size'  # URL中每页显示条数的参数
        page_query_param = 'page'  # URL中页码的参数
        max_page_size = None  # 最大页码数限制

        def __init__(self, page_size=20):
            super().__init__()
            self.page_size = page_size

    def get_data_pagination_with_serializer(self, queryset, pagesize):
        pagination_obj = self.CommentPageNumber(page_size=pagesize)
        pagination_result = pagination_obj.paginate_queryset(queryset, request=self.request, view=self)
        serializer = self.serializer_classes(pagination_result, many=True)
        # pagination_response = pagination_obj.get_paginated_response(serializer.data)
        # return serializer.data, pagination_response.data.get('count')
        return serializer.data

    def get(self, request, *args, **kwargs):
        article_id = self.get_serializer_data().get('article_id')
        if Article.objects.filter(id=article_id).exists():
            article = Article.objects.filter(id=article_id).first()
            comments = article.comments.all()
            outer_comments = comments.filter(is_child=False).order_by('-create_date')
            outer_comments = self.serializer_out(outer_comments, many=True)
            for outer_comment in outer_comments:
                inner_comment = comments.filter(parent_id=outer_comment['id']).order_by('-create_date')
                outer_comment['reply_count'] = len(inner_comment)
                inner_comment = self.get_data_pagination_with_serializer(inner_comment, pagesize=3)
                outer_comment['inner_comments'] = inner_comment

            return self.succeed(data=outer_comments)
        else:
            self.error('没有该文章')


class ListArticleChildComment(BaseAPIView):
    serializer_classes = serializers.ListArticleChildCommentSerializer

    def get(self, request, *args, **kwargs):
        article_id = self.get_serializer_data().get('article_id')
        parent = self.get_serializer_data().get('parent')
        if Article.objects.filter(id=article_id).exists():
            article = Article.objects.filter(id=article_id).first()
            outer_comments = article.comments.all().filter(is_child=True, parent_id=parent).order_by('-create_date')
            # outer_comments = self.serializer_out(outer_comments, many=True)
            return self.pagination_with_serializer(outer_comments)
            # return self.succeed(data=outer_comments)
        else:
            self.error('没有该文章')


# 评论点赞
class ArticleCommentUp(BaseAPIView):
    permission_classes = [IsLogin]
    serializer_classes = serializers.ArticleCommentUpSerializer

    def get(self, request, *args, **kwargs):
        comment_id = self.get_serializer_data().get('comment_id')
        if Comment.objects.filter(id=comment_id).exists():
            Comment.objects.filter(id=comment_id).update(up_count=F('up_count') + 1)
            return self.succeed('点赞成功')
        else:
            self.error('没有查询到该条评论')


# 更新功能写在了上传里
class UpdateArticle(BaseAPIView):

    def post(self, request, *args, **kwargs):
        pass


class UploadFile(BaseAPIView):

    serializer_classes = serializers.UploadFileSeralizer

    def post(self, request, *args, **kwargs):
        data = self.post_serializer_data()
        file = data.get('file')
        file_type = file.content_type.split('/')[1]
        # file = request.FILES.get('file', None)
        file_name = write_file_local(file, file_type)
        if file_name:
            return self.succeed(data={
                'url': 'http://127.0.0.1:8000/file/' + file_name,
                'others': {
                    'text': file.name,
                    'target': '_blank'
                }
            })
        raise self.error('上传失败')


class UploadImage(BaseAPIView):

    serializer_classes = serializers.UploadFileSeralizer

    def post(self, request, *args, **kwargs):
        data = self.post_serializer_data()
        file = data.get('file')
        file_type = file.content_type.split('/')[1]
        file_type = 'jpg' if file_type == 'jpeg' else file_type
        if file_type.lower() not in ['jpg', 'png']:
            raise self.error('上传失败！图片格式不正确')
        file_name = write_file_local(file, file_type)
        if file_name:
            return self.succeed(data={
                'url': 'http://127.0.0.1:8000/file/' + file_name,
                'others': {
                    'alt': file.name
                }
            })
        raise self.error('上传失败')


class UploadMedia(BaseAPIView):

    serializer_classes = serializers.UploadFileSeralizer

    def post(self, request, *args, **kwargs):
        data = self.post_serializer_data()
        file = data.get('file')
        file_type = file.content_type.split('/')[1]
        if file_type.lower() not in ['mp4', 'mp3', 'flv']:
            raise self.error('上传失败！视频格式不正确')
        file_name = write_file_local(file, file_type)
        if file_name:
            return self.succeed(data={
                'url': 'http://127.0.0.1:8000/file/' + file_name,
                'others': {
                    # 'source2': 'movie-alt.ogg',
                    # 'poster': 'movie-image.jpg'
                }
            })
        raise self.error('上传失败')
